/*
# Trabajo Practico 2 Ejercicio 4
# Primera Entrega
#
# - Integrantes:
#	- Martinez, Guillermo	DNI: 34510461
#	- Meli, Marcos			DNI: 31832759
#	- Reyes, Leandro		DNI: 34213699
#	- Rodriguez, Lucas		DNI: 34265017
#	- Cortez, Martin		DNI: 30440023
#
# NOTA: Como la selección de señales queda a elección del programador, solo acolamos señales SIGUSR1
#
*/

#include <unistd.h> 
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include "fifo/fifo.h"

#define LEER		0
#define ESCRIBIR	1

void trata_signal(int);

int alarma=0, _return;
t_cola cola;
t_info_fifo info_fifo;

int main(void)
{
	int _pipe[2],random=0;

	pipe(_pipe);
	_return = fork();
	switch(_return)
	{
		case -1:  /* Error en fork */
			printf("Fallo el fork. SE FINALIZA EJECUCION\n");
			exit(-2);
			break;

		case 0:   /* Tratamiento Hijo */		
			//printf("!Hijo\tPID: %d\tPPID: %d\n", getpid(), getppid());

			if(signal(SIGUSR1, SIG_IGN) == SIG_ERR)		/* HIJO: IGNORA SEÑAL SIGUSR1 */
			{	printf("Fallo el signal"); exit(-1);}
			if(signal(SIGALRM, SIG_IGN) == SIG_ERR)		/* HIJO: IGNORA SEÑAL SIGALRM */
			{	printf("Fallo el signal"); exit(-1);}			

			if(signal(SIGUSR2, trata_signal) == SIG_ERR)
			{	printf("Fallo el signal"); exit(-1);}
	
			close(_pipe[ESCRIBIR]);
			while(1)
			{
				pause();		/* "despertara" al recibir una señal del PADRE */
				read(_pipe[LEER],&random,sizeof(random));
				printf("H: RECIBO: %d\n",random);
			}
			close(_pipe[LEER]);
			break;

		default:  /* Tratamiento Padre */
			//printf("!Padre\tPID: %d\tPPID: %d\tHPID: %d\n", getpid(), getppid(), _return);

			crearcola(&cola);

			if(signal(SIGINT, trata_signal) == SIG_ERR)
			{	printf("Fallo el signal"); exit(-1);}
			if(signal(SIGUSR1, trata_signal) == SIG_ERR)
			{	printf("Fallo el signal"); exit(-1);}
			if(signal(SIGALRM, trata_signal) == SIG_ERR)
			{	printf("Fallo el signal"); exit(-1);}

			close(_pipe[LEER]);
			while(1)
			{
				pause();
				if(!colavacia(&cola) && !alarma)
					{
						sacardecola(&cola, &info_fifo);
						write(_pipe[ESCRIBIR],&info_fifo.random, sizeof(info_fifo.random));
						alarma=1;
						kill(_return,SIGUSR2);
						alarm(2);
					}			
			}
			close(_pipe[ESCRIBIR]);
			wait(NULL);   /* espera la muerte de algun hijo */
			exit(0);
	}
}

void trata_signal(int signum)
{
	switch (signum)
	{
		case SIGINT:	/* SIGINT - Señal para terminar procesos. */
			printf("Terminando procesos Padre e Hijo...\n");
			kill(_return,SIGINT);
			wait(NULL);
			vaciarcola(&cola);
			exit(0);
			break;

		case SIGUSR1:	/* SIGUSR1 - Señal para crear mensaje. */
			//printf("P: Señal SIGUSR1\n");
			info_fifo.random=rand();
			info_fifo.num_signal=signum;
			if(colallena(&cola))
			{
				printf("No hay memoria para acolar. SE FINALIZA EJECUCION\n");
				exit(-2);
			}
			ponerencola(&cola, &info_fifo);
			printf("P: n_signal %d acolo n_random : %d\n", info_fifo.num_signal, info_fifo.random);
			break;

		case SIGUSR2:	/* SIGUSR2 - Señal para que hijo lea mensaje. */
			//printf("H: Señal SIGUSR2\n"); //No tiene trato especial, se utiliza para "despertar" al hijo del pause();
			break;

		case SIGALRM:	/* SIGALRM - Señal de alarma. */
			alarma=0;	//pasaron 2seg. ya podemos volver a enviar
			break;
	}
}
